home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / bc-1_02.lha / bc-1.02 / load.c < prev    next >
C/C++ Source or Header  |  1992-03-04  |  7KB  |  334 lines

  1. /* load.c:  This code "loads" code into the code segments. */
  2.  
  3. /*  This file is part of bc written for MINIX.
  4.     Copyright (C) 1991, 1992 Free Software Foundation, Inc.
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; either version 2 of the License , or
  9.     (at your option) any later version.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program; see the file COPYING.  If not, write to
  18.     the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  
  20.     You may contact the author by:
  21.        e-mail:  phil@cs.wwu.edu
  22.       us-mail:  Philip A. Nelson
  23.                 Computer Science Department, 9062
  24.                 Western Washington University
  25.                 Bellingham, WA 98226-9062
  26.        
  27. *************************************************************************/
  28.  
  29. #include "bcdefs.h"
  30. #include "global.h"
  31. #include "proto.h"
  32.  
  33. /* Load variables. */
  34.  
  35. program_counter load_adr;
  36. char load_str;
  37. char load_const;
  38.  
  39. /* Initialize the load sequence. */
  40. void
  41. init_load ()
  42. {
  43.   clear_func(0);
  44.   load_adr.pc_func = 0;
  45.   load_adr.pc_addr = 0;
  46.   load_str = FALSE;
  47.   load_const = FALSE;
  48. }
  49.  
  50. /* addbyte adds one BYTE to the current code segment. */
  51. void
  52. addbyte (byte)
  53.      char byte;
  54. {
  55.   int seg, offset, func;
  56.  
  57.   /* If there was an error, don't continue. */
  58.   if (had_error) return;
  59.  
  60.   /* Calculate the segment and offset. */
  61.   seg = load_adr.pc_addr >> BC_SEG_LOG;
  62.   offset = load_adr.pc_addr++ % BC_SEG_SIZE;
  63.   func = load_adr.pc_func;
  64.  
  65.   if (seg >= BC_MAX_SEGS)
  66.     {
  67.       yyerror ("Function too big.");
  68.       return;
  69.     }
  70.  
  71.   if (functions[func].f_body[seg] == NULL)
  72.     functions[func].f_body[seg] = (char *) bc_malloc (BC_SEG_SIZE);
  73.  
  74.   /* Store the byte. */
  75.   functions[func].f_body[seg][offset] = byte;
  76.   functions[func].f_code_size++;
  77. }
  78.  
  79.  
  80. /* Define a label LAB to be the current program counter. */
  81.  
  82. void
  83. def_label (lab)
  84.      long lab;
  85. {
  86.   bc_label_group *temp;
  87.   int group, offset, func;
  88.     
  89.   /* Get things ready. */
  90.   group = lab >> BC_LABEL_LOG;
  91.   offset = lab % BC_LABEL_GROUP;
  92.   func = load_adr.pc_func;
  93.   
  94.   /* Make sure there is at least one label group. */
  95.   if (functions[func].f_label == NULL)
  96.     {
  97.       functions[func].f_label = 
  98.     (bc_label_group *) bc_malloc (sizeof(bc_label_group));
  99.       functions[func].f_label->l_next = NULL;
  100.     }
  101.  
  102.   /* Add the label group. */
  103.   temp = functions[func].f_label;
  104.   while (group > 0)
  105.     {
  106.       if (temp->l_next == NULL)
  107.     {
  108.       temp->l_next = (bc_label_group *) bc_malloc (sizeof(bc_label_group));
  109.       temp->l_next->l_next = NULL;
  110.     }
  111.       temp = temp->l_next;
  112.       group --;
  113.     }
  114.  
  115.   /* Define it! */
  116.   temp->l_adrs [offset] = load_adr.pc_addr;
  117. }
  118.  
  119. /* Several instructions have integers in the code.  They
  120.    are all known to be legal longs.  So, no error code
  121.    is added.  STR is the pointer to the load string and
  122.    must be moved to the last non-digit character. */
  123.  
  124. long
  125. long_val (str)
  126.      char **str;
  127. { int  val = 0;
  128.   char neg = FALSE;
  129.  
  130.   if (**str == '-')
  131.     {
  132.       neg = TRUE;
  133.       (*str)++;
  134.     }
  135.   while (isdigit(**str)) 
  136.     val = val*10 + *(*str)++ - '0';
  137.  
  138.   if (neg)
  139.     return -val;
  140.   else
  141.     return val;
  142. }
  143.  
  144.  
  145. /* load_code loads the CODE into the machine. */
  146.  
  147. void
  148. load_code (code)
  149.      char *code;
  150. {
  151.   char *str;
  152.   long  ap_name;    /* auto or parameter name. */
  153.   long  label_no;
  154.   long  vaf_name;    /* variable, array or function number. */
  155.   long  func;
  156.   program_counter save_adr;
  157.  
  158.   /* Initialize. */
  159.   str = code;
  160.    
  161.   /* Scan the code. */
  162.   while (*str != 0)
  163.     {
  164.       /* If there was an error, don't continue. */
  165.       if (had_error) return;
  166.  
  167.       if (load_str)
  168.     {
  169.       if (*str == '"') load_str = FALSE;
  170.       addbyte (*str++);
  171.     }
  172.       else
  173.     if (load_const)
  174.       {
  175.         if (*str == '\n') 
  176.           str++;
  177.         else
  178.           {
  179.         if (*str == ':')
  180.           {
  181.             load_const = FALSE;
  182.             addbyte (*str++);
  183.           }
  184.         else
  185.           if (*str == '.')
  186.             addbyte (*str++);
  187.           else
  188.             if (*str >= 'A')
  189.               addbyte (*str++ + 10 - 'A');
  190.             else
  191.               addbyte (*str++ - '0');
  192.           }
  193.       }
  194.     else
  195.       {
  196.         switch (*str)
  197.           {
  198.  
  199.           case '"':    /* Starts a string. */
  200.         load_str = TRUE;
  201.         break;
  202.  
  203.           case 'N': /* A label */
  204.         str++;
  205.         label_no = long_val (&str);
  206.         def_label (label_no);
  207.         break;
  208.  
  209.           case 'B':  /* Branch to label. */
  210.           case 'J':  /* Jump to label. */
  211.           case 'Z':  /* Branch Zero to label. */
  212.         addbyte(*str++);
  213.         label_no = long_val (&str);
  214.         if (label_no > 65535L)
  215.           {  /* Better message? */
  216.             fprintf (stderr,"Program too big.\n");
  217.             exit(1);
  218.           }
  219.         addbyte ( (char) label_no & 0xFF);
  220.         addbyte ( (char) label_no >> 8);
  221.         break;
  222.  
  223.           case 'F':  /* A function, get the name and initialize it. */
  224.         str++;
  225.         func = long_val (&str);
  226.         clear_func (func);
  227. #if DEBUG > 2
  228.         printf ("Loading function number %d\n", func);
  229. #endif
  230.         /* get the parameters */
  231.         while (*str++ != '.')
  232.           {
  233.             if (*str == '.')
  234.               {
  235.             str++;
  236.             break;
  237.               }
  238.             ap_name = long_val (&str);
  239. #if DEBUG > 2
  240.             printf ("parameter number %d\n", ap_name);
  241. #endif
  242.             functions[(int)func].f_params = 
  243.               nextarg (functions[(int)func].f_params, ap_name);
  244.           }
  245.  
  246.         /* get the auto vars */
  247.         while (*str != '[')
  248.           {
  249.             if (*str == ',') str++;
  250.             ap_name = long_val (&str);
  251. #if DEBUG > 2
  252.             printf ("auto number %d\n", ap_name);
  253. #endif
  254.             functions[(int)func].f_autos = 
  255.               nextarg (functions[(int)func].f_autos, ap_name);
  256.           }
  257.         save_adr = load_adr;
  258.         load_adr.pc_func = func;
  259.         load_adr.pc_addr = 0;
  260.         break;
  261.         
  262.           case ']':  /* A function end */
  263.         functions[load_adr.pc_func].f_defined = TRUE;
  264.         load_adr = save_adr;
  265.         break;
  266.  
  267.           case 'C':  /* Call a function. */
  268.         addbyte (*str++);
  269.         func = long_val (&str);
  270.         if (func < 128)
  271.           addbyte ( (char) func);
  272.         else
  273.           {
  274.             addbyte ((func >> 8) & 0xff | 0x80);
  275.             addbyte (func & 0xff);
  276.           }
  277.         if (*str == ',') str++;
  278.         while (*str != ':')
  279.           addbyte (*str++);
  280.         addbyte (':');
  281.         break;
  282.         
  283.           case 'c':  /* Call a special function. */
  284.         addbyte (*str++);
  285.         addbyte (*str);
  286.         break;
  287.  
  288.           case 'K':  /* A constant.... may have an "F" in it. */
  289.         addbyte (*str);
  290.         load_const = TRUE;
  291.         break;
  292.  
  293.           case 'd':  /* Decrement. */
  294.           case 'i':  /* Increment. */
  295.           case 'l':  /* Load. */
  296.           case 's':  /* Store. */
  297.           case 'A':  /* Array Increment */
  298.           case 'M':  /* Array Decrement */
  299.           case 'L':  /* Array Load */
  300.           case 'S':  /* Array Store */
  301.         addbyte (*str++);
  302.         vaf_name = long_val (&str);
  303.         if (vaf_name < 128)
  304.           addbyte (vaf_name);
  305.         else
  306.           {
  307.             addbyte ((vaf_name >> 8) & 0xff | 0x80);
  308.             addbyte (vaf_name & 0xff);
  309.           }
  310.         break;
  311.  
  312.           case '@':  /* A command! */
  313.         switch (*(++str))
  314.           {
  315.           case 'i':
  316.             init_load ();
  317.             break;
  318.           case 'r':
  319.             execute ();
  320.             break;
  321.           } 
  322.         break;
  323.  
  324.           case '\n':  /* Ignore the newlines */
  325.         break;
  326.         
  327.           default:   /* Anything else */
  328.         addbyte (*str);       
  329.           }
  330.         str++;
  331.       }
  332.     }
  333. }
  334.